#include "kdcmediaplayer.h"

#include <QVBoxLayout>
#include <QList>
#include <QStringList>

#include <KLocale>
#include <KMessageBox>
#include <kdclib.h>

#include "kdcmediaplayerconfig.h"

KDCMediaPlayer::KDCMediaPlayer( QObject *aParent ) : KDCMediaPlayerInterface( aParent ), pWindow( NULL ), pControlPanel( NULL ), pMovie( NULL ), pGui( false ), pIsPlaying( false ), pPos( 0 )
{
	pJob = new KDCMPlayerMencoderJob( KDCMPlayerMencoderJob::MPlayer, this );
	pJob->addArgument( "-quiet" );
	pJob->addArgument( "-noautosub" );
	pJob->addArgument( "-osdlevel", "0" );
	pJob->setAutoDelete( false );
	connect( pJob, SIGNAL( timeChanged( int ) ), this, SLOT( slotTimeChanged( int ) ) );
	connect( pJob, SIGNAL( result( KJob * ) ), this, SLOT( slotResult( KJob * ) ) );
}

KDCMediaPlayer::~KDCMediaPlayer()
{
	deletePtr( pWindow );
	deletePtr( pControlPanel );
	pJob->stop();
	deletePtr( pJob );
}

void KDCMediaPlayer::createGui()
{
	if ( pGui )
		return;
	pWindow = new KDCMPlayerWindow;
	pControlPanel = new KDCMPlayerControlPanel;
	connect( pControlPanel, SIGNAL( playClicked() ), this, SLOT( play() ) );
	connect( pControlPanel, SIGNAL( pauseClicked() ), this, SLOT( pause() ) );
	connect( pControlPanel, SIGNAL( stopClicked() ), this, SLOT( stop() ) );
	connect( pControlPanel, SIGNAL( timeSeekChanged( int ) ), this, SLOT( setSeek( int ) ) );
	connect( pControlPanel, SIGNAL( audioIDChanged( int ) ), pJob, SLOT( changeAudioID( int ) ) );
	connect( pControlPanel, SIGNAL( videoDriverChanged( const QString& ) ), pJob, SLOT( changeVideoDriver( const QString& ) ) );
	pJob->addArgument( "-wid", QString::number( pWindow->displayWindow()->winId() ) );
	pJob->addArgument( "-vo",  KDCMediaPlayerConfig::videoDriver() );
	pGui = true;
}

KDCMPlayerWindow* KDCMediaPlayer::window() const
{
	return pWindow;
}

QWidget* KDCMediaPlayer::controlPanel() const
{
	return pControlPanel;
}

void KDCMediaPlayer::slotTimeChanged( int aValue )
{
	if ( !pMovie->subMovies().isEmpty() )
	{
		int id = pJob->currentMovie();
		if ( aValue == 0 && pPos > 0 )
		{
			++id;
			pJob->setCurrentMovie( id );
		}
		if ( id > 1 )
		{
			int ss = pMovie->metaData()->videoMetaData()->length();;
			for ( int i=0; i<id-1; ++i )
				ss += pMovie->subMovies().at( i )->metaData()->videoMetaData()->length();
			aValue += ss;
		}
	}
	pPos = aValue;
	pControlPanel->setSeek( aValue );
}

void KDCMediaPlayer::stop()
{
	pJob->stop();
	pIsPlaying = false;
}

int KDCMediaPlayer::currentPos() const
{
	return pPos;
}

void KDCMediaPlayer::play()
{
	if ( !pMovie || pIsPlaying )
		return;
	
	QStringList files;
	files.append( pMovie->metaData()->name() ); 
	for ( int i=0; i<pMovie->subMovies().size(); ++i )
		files << pMovie->subMovies().at( i )->metaData()->name();
	pJob->setFiles( files );
	
	if ( pGui )
	{
		QList<int> list;
		for ( int i=0; i<pMovie->audio().size(); ++i )
			list.append( pMovie->audio().at( i )->metaData()->id() );
		pControlPanel->setAudioTrack( list );
		pWindow->setMovieProperties( pMovie->video()->metaData()->width(), pMovie->video()->metaData()->height(), pMovie->video()->metaData()->aspectRatio() );
		pControlPanel->setMaxTime( pMovie->length() );
		pControlPanel->setSeek( 0 );
	}
		
	pJob->start();
	
	pIsPlaying = true;
}

void KDCMediaPlayer::setMovie( KDCMovie *aMovie )
{
	pMovie = aMovie;
}

void KDCMediaPlayer::slotResult( KJob *aJob )
{
	if ( aJob->error() )
	{
		KMessageBox::error( 0, i18n("MediaPlayer has failed with error message:\n") + aJob->errorString() );
		pJob->resetErrors();
	}
	pIsPlaying = false;
}

void KDCMediaPlayer::setSeek( int aValue )
{
	if ( !pMovie )
		return;
	if ( !pMovie->subMovies().isEmpty() )
	{
		int newSum = pMovie->video()->metaData()->length();
		int oldSum = 0;
		int i;
		if ( newSum < aValue )
		{
			for ( i=0; i<pMovie->subMovies().size(); ++i )
			{
				oldSum = newSum;
				newSum += pMovie->subMovies().at( i )->video()->metaData()->length();
				if ( newSum >= aValue )
					break;
			}
		}
		int id = pJob->currentMovie();
		int delta = i + 1 - id;
		if ( delta != 0 )
		{
			pJob->blockSignals( true );
			if ( delta > 0 )
				pJob->playNext( delta );
			else
				if ( delta < 0 )
					pJob->playPrev( qAbs( delta ) );
			pJob->blockSignals( false );
		}
		aValue -= oldSum;
		pJob->setCurrentMovie( id + delta );
	}
	if ( pJob->isPause() )
	{
		pJob->forcePause();
		pJob->setSeek( aValue );
		pJob->forcePause();
	}
	else
		pJob->setSeek( aValue );
}

void KDCMediaPlayer::pause()
{
	pJob->forcePause();
}
